//
// Created by xwt.
//

#include <ctime>
#include <cstdarg>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include "ab_logger.hpp"


namespace anbantech {

    ab_logger_ptr ab_logger::instance = nullptr;
    std::mutex ab_logger::mtx;

    ab_logger::ab_logger(bool console, LogLevel level) {
        this->filename = get_moudule_name() + ".log";
        this->console = console;
        this->level = level;
        file.open(filename,std::ios_base::app);

    }

    ab_logger::~ab_logger() {
        file.close();
    }

    std::string ab_logger::get_current_time() {
        std::time_t t = std::time(nullptr);
        char buffer[20]; // 缓冲区
        std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", std::localtime(&t)); // 格式化时间
        return buffer; // 返回字符串
    }

    std::string ab_logger::get_log_level(LogLevel tmplevel) {
        switch (tmplevel) {
            case DEBUG:
                return "DEBUG";
            case INFO:
                return "INFO";
            case WARN:
                return "WARN";
            case ERROR:
                return "ERROR";
            case FATAL:
                return "FATAL";
            default:
                return "UNKNOWN";
        }
    }

    void ab_logger::log(LogLevel level_in, const char *format, ...) {
        if (level_in >= this->level) {
            std::string log = get_current_time() + " [" + get_log_level(level_in) + "] ";
            char buffer[1024];
            va_list args;
            va_start(args, format);
            vsnprintf(buffer, sizeof(buffer), format, args);
            va_end(args);
            log += std::string(buffer) + "\n";
            file << log;
            file.flush();
            if (console) {
                std::cout << log;
            }
        }
    }
    ab_logger_ptr ab_logger::get_instance(bool console, LogLevel level) {

        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx);
            if (instance == nullptr) {
                instance = ab_logger_ptr(new ab_logger(console, level));
            }
        }

        return instance;
    }

    std::string ab_logger::get_moudule_name() {
        char buffer[256]={0};
        ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1);

        if (length != -1) {
            return basename(buffer);
        } else {
            return "ab_logger";
        }
    }

    void ab_logger::set_log_level(LogLevel l) {
        this->level = l;
    }

} // anbantech